#include <iostream>
#include <memory>
#include <signal.h>
#include "Sock.hpp"
#include "TcpServer.hpp"
#include "Protocol.hpp"
#include "Daemon.hpp"
#include "json/json.h"

using namespace nc_protocol;
 
static void Usage(const std::string proc)
{
    std::cout << "\nUsage:" << proc << " port\n"
              << std::endl;
}

// void handler(int i)
// {
//     std:: cout << "我是测试回调函数" << std::endl;
// }

Response calculatorHelp(const Request &req)
{
    Response resp(0, 0);
    switch (req._rule)
    {
    case '+':
        resp._result = req._x + req._y;
        break;
    case '-':
        resp._result = req._x - req._y;
        break;
    case '*':
        resp._result = req._x * req._y;
        break;
    case '/':
        if (0 == req._y)
            resp._code = 1;
        else
            resp._result = req._x / req._y;
        break;
    case '%':
        if (0 == req._y)
            resp._code = 2;
        else
            resp._result = req._x % req._y;
        break;
    default:
        resp._code = 3;
        break;
    }
    return resp;
}

void calculator(int sock)
{
    std::string str;
    while (true)
    {
        // 1. 读取成功
        bool ret = Recv(sock, &str); // 在这里我们读到了一个请求？
        if (!ret)
            break;
        // 2. 协议解析，保证得到一个完整的报文
        std::cout << "begin: str: " << str << std::endl;
        std::string package = Decode(str);
        if (package.empty())
            continue;
        std::cout << "end: str: " << str << std::endl;
        std::cout << "package: " << package << std::endl;
        // 3. 保证该报文是一个完整的报文
        Request req;
        // 4. 反序列化，字节流 -> 结构化
        req.Deserialization(package); // 反序列化
        // 5. 业务逻辑
        Response res = calculatorHelp(req);
        // 6. 序列化
        std::string respstring = res.serialization(); // 将处理完的数据序列化
        // 7. 添加长度信息，形成一个完整的报文
        // "length\r\ncode result\r\n"
        std::cout << "respString: " << respstring << std::endl;
        respstring = Encode(respstring);
        std::cout << "encode: respString: " << respstring << std::endl;
        // 8. send这里我们暂时先这样写，多路转接的时候，我们再来谈发送的问题
        Send(sock, respstring);
    }
}

int main(int argc, char *argv[])
{
    signal(SIGPIPE, SIG_IGN);
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(1);
    }
    MyDaemon();
    std::unique_ptr<TcpServer> server(new TcpServer(atoi(argv[1])));
    server->BindService(calculator);
    server->Start();

    return 0;
}